package com.shuwen.gcdj.service.auth;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shuwen.gcdj.common.util.http.UserHttpUtil;
import com.shuwen.gcdj.dto.sso.SsoAccessTokenResp;
import com.shuwen.gcdj.dto.sso.SsoAccessTokenRespWrapper;
import com.shuwen.gcdj.dto.sso.SsoNullResp;
import com.shuwen.gcdj.dto.sso.SsoNullRespWrapper;
import com.shuwen.gcdj.dto.sso.SsoRefreshAccessTokenResp;
import com.shuwen.gcdj.dto.sso.SsoRefreshAccessTokenRespWrapper;
import com.shuwen.gcdj.dto.sso.SsoUserResp;
import com.shuwen.gcdj.dto.sso.SsoUserRespWrapper;
import com.shuwen.gcdj.dto.sso.SsoValidResp;
import com.shuwen.gcdj.dto.sso.SsoValidRespWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

@Service
@AllArgsConstructor
@Slf4j
public class SsoService {
    /**
     * 天河配置
     */
    private final SsoConfig ssoConfig;

    private String buildApiUrl(String biz) {
        return ssoConfig.getUrl() + biz;
    }

    /**
     * 根据code获取access_token
     *
     * @param code String
     * @return SsoAccessTokenResp
     */
    public SsoAccessTokenResp getAccessToken(String code) {
        String url = buildApiUrl("access_token");
        url += String.format("?grant_type=authorization_code&client_id=%s&client_secret=%s&code=%s", ssoConfig.getClientId(), ssoConfig.getSk(), code);
        ResponseEntity<String> resp = UserHttpUtil.sendGet(url);
        if (resp == null || resp.getStatusCode() != HttpStatus.OK) {
            log.error("error-1: SsoService.getAccessToken(code = {}) httpCode error: 获取access_token失败, url = {}, resp = {}", code, url, resp);
            return null;
        }
        String body = resp.getBody();
        if (body == null) {
            return null;
        }

        JSONObject obj = JSON.parseObject(body);
        SsoAccessTokenRespWrapper result = JSON.toJavaObject(obj, SsoAccessTokenRespWrapper.class);
        if (result == null) {
            log.error("error-2: SsoService.getAccessToken(code = {}) JSON.ParseObject({}) error.", code, body);
            return null;
        }

        if (result.getCode() != 0) {
            log.error("error-3: SsoService.getAccessToken(code = {}) result = {}, error.", code, result);
            return null;
        }
        return result.getData();
    }

    /**
     * 刷新access_token
     *
     * @param accessToken String
     * @return SsoRefreshAccessTokenResp
     */
    public SsoRefreshAccessTokenResp refreshAccessToken(String accessToken) {
        String url = buildApiUrl("refresh_token");
        url += String.format("?grant_type=refresh_token&client_id=%s&client_secret=%s&refresh_token=%s", ssoConfig.getClientId(), ssoConfig.getSk(), accessToken);
        ResponseEntity<String> resp = UserHttpUtil.sendGet(url);
        if (resp == null || resp.getStatusCode() != HttpStatus.OK) {
            log.error("SsoService.refreshAccessToken(accessToken = {}) httpCode error: 获取access_token失败", accessToken);
            return null;
        }

        String body = resp.getBody();
        if (body == null) {
            return null;
        }

        JSONObject obj = JSON.parseObject(body);
        SsoRefreshAccessTokenRespWrapper result = JSON.toJavaObject(obj, SsoRefreshAccessTokenRespWrapper.class);
        if (result == null) {
            log.error("SsoService.refreshAccessToken(accessToken = {}) JSON.ParseObject({}) error.", accessToken, body);
            return null;
        }

        if (result.getCode() != 0) {
            log.error("SsoService.refreshAccessToken(accessToken = {}) result = {}, error.", accessToken, result);
            return null;
        }
        return result.getData();
    }

    /**
     * 根据access_token获取用户信息
     *
     * @param accessToken String
     * @return SsoUserResp
     */
    public SsoUserResp getUserInfo(String accessToken) {
        String url = buildApiUrl("userinfo");
        url += String.format("?access_token=%s", accessToken);
        ResponseEntity<String> resp = UserHttpUtil.sendGet(url);
        if (resp == null || resp.getStatusCode() != HttpStatus.OK) {
            log.error("SsoService.getUserInfo(accessToken = {}) httpCode error: 获取access_token失败", accessToken);
            return null;
        }

        String body = resp.getBody();
        if (body == null) {
            return null;
        }

        JSONObject obj = JSON.parseObject(body);
        SsoUserRespWrapper result = JSON.toJavaObject(obj, SsoUserRespWrapper.class);
        if (result == null) {
            log.error("SsoService.getUserInfo(accessToken = {}) JSON.ParseObject({}) error.", accessToken, body);
            return null;
        }

        if (result.getCode() != 0) {
            log.error("SsoService.getUserInfo(accessToken = {}) result = {}, error.", accessToken, result);
            return null;
        }
        return result.getData();
    }

    /**
     * 验证access_token有效性
     *
     * @param accessToken String
     * @return SsoValidResp
     */
    public SsoValidResp validAccessToken(String accessToken) {
        String url = buildApiUrl("check_token");
        url += String.format("?token_type_hint=access_token&client_id=%s&client_secret=%s&token=%s", ssoConfig.getClientId(), ssoConfig.getSk(), accessToken);
        ResponseEntity<String> resp = UserHttpUtil.sendGet(url);
        if (resp == null || resp.getStatusCode() != HttpStatus.OK) {
            log.error("SsoService.validAccessToken(accessToken = {}) httpCode error: 获取access_token失败", accessToken);
            return null;
        }

        String body = resp.getBody();
        if (body == null) {
            return null;
        }

        JSONObject obj = JSON.parseObject(body);
        SsoValidRespWrapper result = JSON.toJavaObject(obj, SsoValidRespWrapper.class);
        if (result == null) {
            log.error("SsoService.validAccessToken(accessToken = {}) JSON.ParseObject({}) error.", accessToken, body);
            return null;
        }

        if (result.getCode() != 0) {
            log.error("SsoService.validAccessToken(accessToken = {}) result = {}, error.", accessToken, result);
            return null;
        }
        return result.getData();
    }

    /**
     * 退出登录
     *
     * @param accessToken String
     * @return SsoRespWrapper<SsoNullResp>
     */
    public SsoNullResp logout(String accessToken) {
        String url = buildApiUrl("logout");
        url += "?access_token=" + accessToken;
        ResponseEntity<String> resp = UserHttpUtil.sendGet(url);
        if (resp == null || resp.getStatusCode() != HttpStatus.OK) {
            log.error("SsoService.logout(accessToken = {}) httpCode error: 获取access_token失败", accessToken);
            return null;
        }

        String body = resp.getBody();
        if (body == null) {
            return null;
        }

        JSONObject obj = JSON.parseObject(body);
        SsoNullRespWrapper result = JSON.toJavaObject(obj, SsoNullRespWrapper.class);
        if (result == null) {
            log.error("SsoService.logout(accessToken = {}) JSON.ParseObject({}) error.", accessToken, body);
            return null;
        }

        if (result.getCode() != 0) {
            log.error("SsoService.logout(accessToken = {}) result = {}, error.", accessToken, result);
            return null;
        }

        return result.getData();
    }
}
